package com.xm.util; /**
 * Enrich your life everyday, code is mystery. ------------------------------------------------------------- Author
 * Version Time ------------------------------------------------------------- liu-guoping 1.0.0 2018年2月9日 上午10:24:48
 * ------------------------------------------------------------- Copyright © 2015–2020 All rights reserved.
 */

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.xm.util.old.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.TimeZone;

/**
 * Function: jackson json 处理工具类
 *
 * Author：liu-guoping
 * 
 * Time：2018年2月9日 上午10:24:48
 */
public abstract class JacksonUtil {
    /**
     * 日志对象
     */
    private static final Logger log = LoggerFactory.getLogger(JacksonUtil.class);

    /**
     * 对象转换成json字符串
     * 
     * @param object
     *            待转换的对象
     * @return
     */
    public static String toJson(Object object) {
        if (object != null) {
            try {
                return getMapper().writeValueAsString(object);
            } catch (Exception e) {
                log.error("对象转换成json字符串错误：object=" + object, e);
            }
        }
        return null;
    }

    /**
     * json字符串转换成对象
     * 
     * @param json
     *            待转换的json字符串
     * @param clazz
     *            转换的目标对象类
     * @return
     */
    public static <T> T fromJson(String json, Class<T> clazz) {
        if (StringUtil.isNullOrEmpty(json) || clazz == null) {
            return null;
        }
        try {
            return getMapper().readValue(json, clazz);
        } catch (Exception e) {
            log.error("json字符串转换成对象错误：json=" + json + ",clazz=" + clazz, e);
        }
        return null;
    }

    /**
     * json字符串转换成List对象
     * 
     * @param json
     *            待转换的json字符串
     * @param clazz
     *            转换的目标对象类
     * @return
     */
    public static <T> List<T> listFromJson(String json, Class<T> clazz) {
        if (StringUtil.isNullOrEmpty(json) || clazz == null) {
            return null;
        }
        try {
            ObjectMapper mapper = getMapper();
            JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, clazz);
            return mapper.readValue(json, javaType);
        } catch (Exception e) {
            log.error("json字符串转换成List对象错误：json=" + json + ",clazz=" + clazz, e);
        }
        return null;
    }

    /**
     * json字符串转换成对象
     * 
     * @param json
     *            待转换的json字符串
     * @param topClass
     *            转换的目标对象类
     * @param elementClasses
     *            转换的目标对象类的子对象类
     * @return
     */
    public static <T> T collectionFromJson(String json, Class<T> topClass, Class<?>... elementClasses) {
        if (StringUtil.isNullOrEmpty(json)) {
            return null;
        }
        try {
            if (elementClasses == null || elementClasses.length == 0) {
                return fromJson(json, topClass);
            }
            ObjectMapper mapper = getMapper();
            JavaType javaType = mapper.getTypeFactory().constructParametricType(topClass, elementClasses);
            return mapper.readValue(json, javaType);
        } catch (Exception e) {
            log.error("json字符串转换成集合对象错误：json=" + json + ",clazz=" + topClass + ",elementClasses=" + elementClasses, e);
        }
        return null;
    }

    /**
     * 将JSON字符串转换成Map
     * 
     * @param <K>
     * @param <V>
     * @param json
     *            JSON字符串
     * @param k
     *            Map key Type
     * @param v
     *            Map value Type
     * @return Map<K,V>对象
     */
    public static <K, V> Map<K, V> mapFromJson(String json, Class<K> k, Class<V> v) {
        if (StringUtil.isNullOrEmpty(json) || k == null || v == null) {
            return null;
        }
        try {
            return getMapper().readValue(json, getMapJavaType(k, v));
        } catch (Exception e) {
            log.error("将JSON字符串转换成Map错误：" + json, e);
        }
        return null;
    }

    /**
     * 将JSON字符串转换成List<Map>
     * 
     * @param json
     *            JSON字符串
     * @param k
     *            key Type
     * @param v
     *            value Type
     * @return
     */
    public static <K, V> List<Map<K, V>> listMapFromJson(String json, Class<K> k, Class<V> v) {
        if (StringUtil.isNullOrEmpty(json) || k == null || v == null) {
            return null;
        }
        try {
            JavaType javaType = getMapper().getTypeFactory().constructCollectionType(List.class, getMapJavaType(k, v));
            return getMapper().readValue(json, javaType);
        } catch (Exception e) {
            log.error("将JSON字符串转换成Map错误：" + json, e);
        }
        return null;
    }

    /**
     * 获取json转换对象
     * 
     * @return
     */
    public static ObjectMapper getMapper() {
        ObjectMapper mapper = new ObjectMapper();
        // 忽略空属性
        mapper.setSerializationInclusion(Include.NON_EMPTY);
        // 忽略对象中没有的属性
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
        mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
        mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        // 解决时区差8小时问题
        mapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));

        return mapper;
    }

    /**
     * 获取Map类型的JavaType对象
     * 
     * @param k Map key Type
     * @param v
     *            Map value Type
     * @return Map类型的JavaType对象
     */
    private static <K, V> JavaType getMapJavaType(Class<K> k, Class<V> v) {
        TypeFactory factory = getMapper().getTypeFactory();
        return factory.constructMapType(Map.class, factory.constructType(k), factory.constructType(v));
    }
}
